﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace Authority
{
    /// <summary>
    /// 权限信息设置
    /// </summary>
    [Serializable]
    public class RoleManager : List<Role>
    {
        /// <summary>
        /// 获取或设置配置的实例
        /// </summary>
        public static RoleManager Instance { get; set; }

        /// <summary>
        /// 获取配置文件路径
        /// </summary>
        public static string SettingFile
        {
            get
            {
                return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Setting.config");
            }
        }

        /// <summary>
        /// 保存配置信息
        /// </summary>        
        /// <returns></returns>
        public bool Save()
        {
            using (FileStream stream = new FileStream(SettingFile, FileMode.OpenOrCreate))
            {
                var serializer = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
                serializer.Serialize(stream, this);
            }
            return true;
        }


        /// <summary>
        /// 从文件中加载配置文件 
        /// </summary>
        /// <returns></returns>
        private static RoleManager Load()
        {
            if (File.Exists(SettingFile) == false)
            {
                return new RoleManager();
            }

            using (FileStream stream = new FileStream(SettingFile, FileMode.Open))
            {
                var serializer = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
                var setting = serializer.Deserialize(stream) as RoleManager;
                return setting;
            }
        }

        /// <summary>
        /// 补全角色
        /// </summary>
        /// <param name="setting">设置</param>
        /// <param name="roleIdArray">角色ID集合</param>
        private static void SetRoles(RoleManager setting, IEnumerable<Guid> roleIdArray)
        {
            var q = from rid in roleIdArray
                    join role in setting
                    on rid equals role.ID
                    into g
                    from item in g.DefaultIfEmpty()
                    where item == null
                    select new Role { ID = rid };

            setting.AddRange(q);
        }

        /// <summary>
        /// 补全视图
        /// </summary>
        /// <param name="setting">设置</param>
        private static void SetViews(RoleManager setting)
        {
            foreach (var role in setting)
            {
                var views = View.All();
                var q = from v1 in views
                        join v2 in role.ViewList
                        on v1.Value equals v2.Value
                        into g
                        from item in g.DefaultIfEmpty()
                        select item == null ? v1 : item;

                role.ViewList = q.ToList();
            }
        }

        /// <summary>
        /// 补全功能
        /// </summary>
        /// <param name="setting">设置</param>
        private static void SetActions(RoleManager setting)
        {
            foreach (var role in setting)
            {
                foreach (var view in role.ViewList)
                {
                    var field = typeof(ViewEnum).GetField(view.Value.ToString(), BindingFlags.Static | BindingFlags.Public);
                    var includes = Attribute.GetCustomAttributes(field, typeof(IncludeAttribute)) as IncludeAttribute[];

                    var actionList = new List<ActionEnum>();
                    if (includes != null)
                    {
                        actionList.AddRange(includes.OrderBy(item => item.Index).Select(item => item.Action));
                    }

                    var q = from a1 in actionList
                            join a2 in view.AcitonList
                            on a1 equals a2.Value
                            into g
                            from item in g.DefaultIfEmpty()
                            where item == null
                            select new Action(a1);

                    view.AcitonList.AddRange(q);
                }
            }
        }


        /// <summary>
        /// 返回加载获取配置信息      
        /// </summary>     
        /// <param name="roleID">角色ID</param>
        /// <returns></returns>
        public static RoleManager Load(IEnumerable<Guid> roleID)
        {
            var setting = RoleManager.Load();
            RoleManager.SetRoles(setting, roleID);
            RoleManager.SetViews(setting);
            RoleManager.SetActions(setting);
            return setting;
        }
    }
}
